package vn.edu.saigontech.ncms.web.offering.report;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import vn.edu.saigontech.ncms.model.enumeration.TeachingInterruptionReason;
import vn.edu.saigontech.ncms.model.info.Offering;
import vn.edu.saigontech.ncms.model.info.OfferingMember;
import vn.edu.saigontech.ncms.model.teaching.TeachingInterruption;
import vn.edu.saigontech.ncms.service.DayOffService;
import vn.edu.saigontech.ncms.service.OfferingMemberService;
import vn.edu.saigontech.ncms.service.OfferingService;
import vn.edu.saigontech.ncms.util.DateUtil;

public class CheckingAttendanceVO {

	private Offering offering;
	private Collection<OfferingMember> offeringMembers;
	private Collection<Date> days;
	
	private Map<String, Integer> months = new LinkedHashMap<String, Integer>();
	private Map<Integer, Integer> weeks = new LinkedHashMap<Integer, Integer>();
	
	private int fromWeek;
	private int toWeek;
	
	public CheckingAttendanceVO(Offering offering, boolean includeInactiveMembers) {
		this.offering = offering;
		if(includeInactiveMembers) {
			this.offeringMembers = OfferingMemberService.INSTANCE.findByOfferingId(offering.getId());
		}
		else {
			this.offeringMembers = OfferingMemberService.INSTANCE.findByOfferingId(offering.getId(), true);
		}
		
		this.init();
	}
	
	public CheckingAttendanceVO(Offering offering, boolean active, int fromWeek, int toWeek) {
		this.offering = offering;
		this.fromWeek = fromWeek;
		this.toWeek = toWeek;
		if(active) {
			this.offeringMembers = OfferingMemberService.INSTANCE.findByOfferingId(offering.getId());
		}
		else {
			this.offeringMembers = OfferingMemberService.INSTANCE.findByOfferingId(offering.getId(), true);
		}
		this.init2(fromWeek, toWeek);
	}

	private void init() {
		this.days = OfferingService.INSTANCE.findTeachingDays(this.offering.getId());
		for(Date date : this.days) {
			String month = (DateUtil.getMonth(date) + 1) + "/" + DateUtil.getYear(date);
			if(this.months.keySet().contains(month)) {
				this.months.put(month, this.months.get(month) + 1);
			}
			else {
				this.months.put(month, 1);
			}
			Integer week = DateUtil.getWeekOfYear(date);
			if(this.weeks.keySet().contains(week)) {
				this.weeks.put(week, this.weeks.get(week) + 1);
			}
			else {
				weeks.put(week, 1);
			}
		}
	}
	
	private void init2(int fromWeek, int toWeek) {
		this.init1();
		List<Date> tmpDays = new ArrayList<Date>();
		Map<Integer, Integer> tmpWeeks = new LinkedHashMap<Integer, Integer>();
		
		List<Entry<Integer, Integer>> list = new ArrayList<Entry<Integer,Integer>>(this.weeks.entrySet());
		for(int i = 0; i < list.size(); i++) {
			int week = i + 1;
			if(fromWeek <= week && week <= toWeek) {
				Entry<Integer, Integer> entry = list.get(i);
				tmpWeeks.put(entry.getKey(), entry.getValue());
			}
		}
		for(Date date : this.days) {
			Integer week = DateUtil.getWeekOfYear(date);
			if(tmpWeeks.keySet().contains(week)) {
				String month = (DateUtil.getMonth(date) + 1) + "/" + DateUtil.getYear(date);
				if(this.months.keySet().contains(month)) {
					this.months.put(month, this.months.get(month) + 1);
				}
				else {
					this.months.put(month, 1);
				}
				tmpDays.add(date);
			}
		}
		this.weeks = tmpWeeks;
		this.days = tmpDays;
	}
	
	private void init1() {
		this.days = OfferingService.INSTANCE.findTeachingDays(this.offering.getId());
		for(Date date : this.days) {
			Integer week = DateUtil.getWeekOfYear(date);
			if(this.weeks.keySet().contains(week)) {
				this.weeks.put(week, this.weeks.get(week) + 1);
			}
			else {
				this.weeks.put(week, 1);
			}
		}
	}
	
	public int interrupted(Date date) {
		Collection<TeachingInterruption> interruptions = this.offering.getInstructorInterruptions(TeachingInterruptionReason.CANCEL.name());
		for(TeachingInterruption each : interruptions) {
			if(each.contains(date)) {
				return 1;
			}
		}
		if(DayOffService.INSTANCE.exists(date)) {
			return 2;
		}
		return 0;
	}
	
	public int getDays(String month) {
		return this.months.get(month);
	}
	
	public Collection<Date> getDays() {
		return days;
	}
	
	public Collection<String> getMonths() {
		return this.months.keySet();
	}

	public Map<Integer, Integer> getWeeks() {
		return weeks;
	}

	public Offering getOffering() {
		return offering;
	}

	public Collection<OfferingMember> getOfferingMembers() {
		return offeringMembers;
	}

	public int getFromWeek() {
		return fromWeek;
	}

	public void setFromWeek(int fromWeek) {
		this.fromWeek = fromWeek;
	}

	public int getToWeek() {
		return toWeek;
	}

	public void setToWeek(int toWeek) {
		this.toWeek = toWeek;
	}
	
	
}
